#include "cmdpboc.h"

U08  gCmdBuffer[ICC_APDU_Sed_MAXBUF];                  
U08  gpRcvBuffer[ICC_APDU_Rcv_MAXBUF];

U32  Grcv_Len;

U32 ICF_GetChallenge4B( U08 *Rnd, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0x84;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x04;	//Le
	
	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 5, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }
	
	if( Grcv_Len < 2)
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	if( rcode != 0x9000 )
	{ return rcode; }

	CurCalc_DataCpy( Rnd, gpRcvBuffer, 4 ); 
	return rcode;
}

U32 ICF_SelectAID( const char *AID, U32 ilen, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0xA4;	//INS
	gCmdBuffer[2] = 0x04;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = ilen;	//Lc
	CurCalc_DataCpy( gCmdBuffer+5, (U08*)AID, ilen );
	
	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, ilen+5, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }
	
	if( Grcv_Len < 2 )	
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;

}
U32 ICF_SelectSFI( const char *SFI, U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0xA4;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x02;	//Lc
	CurCalc_DataCpy( gCmdBuffer+5, (U08*)SFI, 2 );
	
	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 2+5, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }
	
	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}
/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_ReadBinaryFile( U08 SFI, U08 Offset, U08 BytesToRead, U32 ich )
*
* 函数功能：读取二进制文件
*
* 函数输入：SFI			文件标识
*			Offset		偏移量
*			BytesToRead	读取的数据长度
*			ich			接口		
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_ReadBinaryFile( U08 SFI, U08 Offset, U08 BytesToRead, U32 ich )
{
	unsigned short rcode;
	
	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0xB0;	//INS
	gCmdBuffer[2] = 0x80 | ( SFI & 0x1F );	//P1
	gCmdBuffer[3] = Offset;	//P2
	gCmdBuffer[4] = BytesToRead;	//Le

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 5, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_WriteBinaryFile( U08 SFI, U08 Offset, U08 BytesToWrite, U08 *DataUnit, U32 ich )
*
* 函数功能：写二进制文件
*
* 函数输入：SFI				文件标识
*			Offset			偏移量
*			BytesToWrite	写入的数据长度
*			DataUnit		需要写入的数据
*			ich				接口		
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_WriteBinaryFile( U08 SFI, U08 Offset, U08 BytesToWrite, U08 *DataUnit, U32 ich )
{
	unsigned short rcode;
	
	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0xD6;	//INS
	gCmdBuffer[2] = 0x80 | (SFI &0x1F);	//P1
	gCmdBuffer[3] = Offset;	//P2
	gCmdBuffer[4] = BytesToWrite;	//Lc
	
	if( BytesToWrite > ( ICC_APDU_Sed_MAXBUF + 5 ) )
	{ return 1; }
	CurCalc_DataCpy( gCmdBuffer+5, DataUnit, BytesToWrite );
	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, BytesToWrite+0x05, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_ReadRecord( U08 SFI, U08 recordnumber, U08 RecordLength, U32 ich )
*
* 函数功能：读取一条记录文件
*
* 函数输入：SFI				文件标识
*			recordnumber	记录编号
*			RecordLength	记录长度
*			ich				接口		
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_ReadRecord( U08 SFI, U08 recordnumber, U08 RecordLength, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0xB2;	//INS
	gCmdBuffer[2] = recordnumber;	//P1
	gCmdBuffer[3] = 0x04 | ((SFI <<3)&0xF8);	//P2
	gCmdBuffer[4] = RecordLength;	//Le

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x05, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}
 
/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_GetBalanceEP( U32 *bl, U32 ich )
*
* 函数功能：读取电子钱包余额
*
* 函数输入：ich				接口			
*                
* 函数输出：bl				卡余额
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_GetBalanceEP( U32 *bl, U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x5C;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x02;	//P2	‘01’用于ED(电子存折，需要个人密码PIN ‘02’用于EP(电子钱包)
	gCmdBuffer[4] = 0x04;	//Le

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x05, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	if( rcode == 0x9000 )
	{ CurCalc_HEXtoBCD_Proc( 4, gpRcvBuffer, 4, 0, 0, bl ); }

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_GetBalanceED( U32 *bl, U32 ich )
*
* 函数功能：读取电子存折余额
*
* 函数输入：ich				接口			
*                
* 函数输出：bl				卡余额
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_GetBalanceED( U32 *bl, U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x5C;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x02;	//P2	‘01’用于ED(电子存折，需要个人密码PIN ‘02’用于EP(电子钱包)
	gCmdBuffer[4] = 0x04;	//Le

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x05, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	if( rcode == 0x9000 )
	{ CurCalc_HEXtoBCD_Proc( 4, gpRcvBuffer, 4, 0, 0, bl ); }

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_GetTransactionProof( U08 TransType, U08 *CTC, U32 ich )
*
* 函数功能：获取交易验证码
*
* 函数输入：TransType		交易类型
*			CTC				交易计数
*			ich				接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_GetTransactionProof( U08 TransType, U08 *CTC, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x5A;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = TransType;	//P2
	gCmdBuffer[4] = 0x02;	//Lc
	
	CurCalc_DataCpy(gCmdBuffer+5, CTC,2);
	gCmdBuffer[7] = 0x08;	//Le
	

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x08, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_InitForPurchaseEP( U08 KeyIndex, U08 *Amont, U08 *TermID, U32 ich )
*
* 函数功能：消费初始化
*
* 函数输入：KeyIndex		密钥索引号
*			Amont			交易金额
*			TermID			终端机编号
*			ich				接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_InitForPurchaseEP( U08 KeyIndex, U08 *Amont, U08 *TermID, U32 ich )								   
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x50;	//INS
	gCmdBuffer[2] = 0x01;	//P1		01 消费初始化 02 取现初始化
	gCmdBuffer[3] = 0x02;	//P2		‘01’用于ED ‘02’用于EP
	gCmdBuffer[4] = 0x0B;	//Lc
	
	gCmdBuffer[5] = KeyIndex;
	CurCalc_DataCpy( gCmdBuffer+6,  Amont,  4 );
	CurCalc_DataCpy( gCmdBuffer+10, TermID, 6 );
	//gCmdBuffer[0x10] = 0x0F;	//Le

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x10, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_DebitForPurchase( U08 *TTC, U08 *CurrentTime, U08 *MAC1, U32 ich )
*
* 函数功能：圈存交易
*
* 函数输入：TTC				TTC值
*			CurrentTime		交易时间
*			MAC1			MAC1值
*			ich				接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_DebitForPurchase( U08 *TTC, U08 *CurrentTime, U08 *MAC1, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x54;	//INS
	gCmdBuffer[2] = 0x01;	//P1		01 消费初始化 02 取现初始化
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x0F;	//Lc
	
	CurCalc_DataCpy( gCmdBuffer+5,    TTC, 4 );		   	//终端交易序号 
	CurCalc_DataCpy( gCmdBuffer+9,    CurrentTime, 7 ); //交易时间 
	CurCalc_DataCpy( gCmdBuffer+0x10, MAC1, 4 );	   	//MAC1值 
	//gCmdBuffer[0x14] = 0x08;	//Le
	
	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x14, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_InitSamForPurchase( U08 *icc, 
*                          				U08 *CTC, 
*										U08 *Amont, 
*		                   				U08 *CurrentTime, 
*										U08 KeyVer, 
*										U08 KeyDrk,
*		                    			U08 *ASN, 
*										U08 *MakeCardId, 
*										U32 ich )
*
* 函数功能：圈存交易
*
* 函数输入：icc         IC卡产生的随机数
*  			CTC         卡交易序号
*    		Amont       交易金额
*   		CurrentTime 当前时间
*   		KeyVer      密钥版本
*     		KeyDrk		密钥算法标识
*   		ASN         卡序号
*    		MakeCardId  成员标识
*			ich			接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_InitSamForPurchase( U08 *icc, 
                            U08 *CTC, 
							U08 *Amont, 
		                    U08 *CurrentTime, 
							U08 KeyVer, 
							U08 KeyDrk,
		                    U08 *ASN, 
							U08 *MakeCardId, 
							U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x70;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x24;	//Lc
	
	CurCalc_DataCpy(gCmdBuffer+5, icc,4);					//随机数    						 
	CurCalc_DataCpy(gCmdBuffer+9, CTC,2);					//脱机交易序号 						 
	CurCalc_DataCpy(gCmdBuffer+11, Amont,4);				//交易金额 									 
	gCmdBuffer[15] = 0x06;									//交易类型标识直接送#91H					 
	CurCalc_DataCpy(gCmdBuffer+16, CurrentTime,7);	    	//交易时间 										 
	gCmdBuffer[23] = KeyVer;								 
	gCmdBuffer[24] = KeyDrk;								//密钥算法标识 									 
	CurCalc_DataCpy(gCmdBuffer+25,ASN,8);					//卡号  注意，这里只使用后8位			 
	CurCalc_DataCpy(gCmdBuffer+33,MakeCardId,8);			//成员标识								 
	gCmdBuffer[41] = 0x08;	//Le


	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x2A, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_CreditSamForPurchase( U08 *MAC2, U32 ich )
*
* 函数功能：MAC2 校 验
*
* 函数输入：MAC2		MAC2值
*			ich			接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_CreditSamForPurchase( U08 *MAC2, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x72;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x04;	//Lc
	
	CurCalc_DataCpy( gCmdBuffer+5, MAC2, 4 );				//MAC送发送缓冲
	
	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x29, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_InitSamForDes( U32 ich )
*
* 函数功能：加密运算
*
* 函数输入：
*			ich			接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_InitSamForDes( U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x1A;	//INS
	gCmdBuffer[2] = 0x45;	//P1 PSAM密钥用途号 08
	gCmdBuffer[3] = 0x01;	//P2 //gCardInfo.PsamPasWodVer;	//PSAM密钥版本号
	gCmdBuffer[4] = 0x10;	//Lc	//临时秘钥分散系数长度

	CurCalc_DataCpy( gCmdBuffer+5, TradeInformation.CardASN, 8 );
	CurCalc_DataCpy( gCmdBuffer+13, TradeInformation.CityCode, 2 );
	CurCalc_DataSet( gCmdBuffer+15, 0xFF, 6 );
	CurCalc_DataSet( gCmdBuffer+16, 0x00, 5 );
	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x15, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_SamDESCrypt( U08 *iniCbc, U32 ich )
*
* 函数功能：加密运算
*
* 函数输入：iniCbc		数据
*			ich			接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_SamDESCrypt( U08 *iniCbc, U32 ich )
{
	U32 rcode,i;

	//第一重计算
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0xFA;	//INS
	gCmdBuffer[2] = 0x05;	//P1,MAC计算,无后续块,有初始值			zj 2008-11-25 13:06
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x10;	//Lc //成交数据长度	 zj 2008-11-24 13:06
	
	for(i=0;i<4;i++)
	{ gCmdBuffer[i+5] = iniCbc[i]; } //成交数据送发送缓冲区
	
	gCmdBuffer[9]  = 0x00;
	gCmdBuffer[10] = 0x00;	
	gCmdBuffer[11] = 0x00;	
	gCmdBuffer[12] = 0x00;

	gCmdBuffer[13] = 0x84;
	gCmdBuffer[14] = 0x1E;	
	gCmdBuffer[15] = 0x00;	
	gCmdBuffer[16] = 0x00;
	gCmdBuffer[17] = 0x04;

	gCmdBuffer[18] = 0x80;	
	gCmdBuffer[19] = 0x00;	
	gCmdBuffer[20] = 0x00;

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x15, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_CardBlock( U08 BytesToWrite, U08 *DataUnit, U32 ich )
*
* 函数功能：锁卡命令
*
* 函数输入：iniCbc		数据
*			ich			接口			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_CardBlock( U08 BytesToWrite, U08 *DataUnit, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x84;	//CLA
	gCmdBuffer[1] = 0x1E;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x04;	//Lc
	
	CurCalc_DataCpy(gCmdBuffer+5,DataUnit,BytesToWrite);

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, BytesToWrite+0x05, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_InitSamForDes_ToEXAUTN( U08 KeyVer, U08 *Icc, U08 *citycode, U32 ich )
*
* 函数功能：PSAM初始化加密运算 在对用户卡进行外部认证时，取得随机数后对PSAM卡进行初始化加密运算
*
* 函数输入：KeyVer		密钥版本
*			Icc 		应用序列号的后8字节
*			citycode	城市代码
*			ich			卡座			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_InitSamForDes_ToEXAUTN( U08 KeyVer, U08 *Icc, U08 *citycode, U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0x1A;	//INS
	gCmdBuffer[2] = 0x27;	//P1 校园一卡通中，外部认证密钥类型为7（加密密钥），低五位是密钥类型，高三位是分散级数，目前对应用序列号（后8字节）采用一级分散
	gCmdBuffer[3] = KeyVer;	//P2 PSAM密钥版本号
	gCmdBuffer[4] = 0x08;	//Lc 加密数据长度

	memcpy( gCmdBuffer+5, Icc, 8 );
	//memcpy( gCmdBuffer+13, citycode, 2 );
	//memset( gCmdBuffer+15, 0xFF, 6 );

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x0d, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	return rcode; 
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_SamDESCrypt_ToEXAUTN( U08 *Icc, U32 ich )
*
* 函数功能：在对用户卡进行外部认证时，让PSAM卡对取得的随机数按指定密钥版本进行加密运算
*
* 函数输入：
*			Icc 		4字节随机数
*			ich			卡座			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_SamDESCrypt_ToEXAUTN( U08 *Icc, U32 ich )
{
	U32 rcode;
	
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0xFA;	//INS
	gCmdBuffer[2] = 0x00;	//P1 无后续块的加密计算
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x08;	//Lc 加密数据长度，4字节的随机数，4字节的0
	//填4字节的随机数
	memcpy( gCmdBuffer+5, Icc, 4 );
	//填4字节的0补齐8字节
	memset( gCmdBuffer+9, 0, 4 );

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x0d, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	return rcode; 
}
  
/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_ExternalAuthentication( U08 KeyVer, U08 *Info, U32 ich )
*
* 函数功能：用户卡外部认证命令
*			用指定的密钥版本对用户卡进行外部认证
*
* 函数输入：KeyVer		密钥版本
*			Info       	经PSAM卡加密过的数据
*			ich			卡座			
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_ExternalAuthentication( U08 KeyVer, U08 *Info, U32 ich )
{
	U32 rcode;

	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0x82;	//INS
	gCmdBuffer[2] = 0x00;	//P1 
	gCmdBuffer[3] = KeyVer;	//P2 用户卡密钥版本号
	gCmdBuffer[4] = 0x08;	//Lc 加密数据长度
	//填8字节经过PSAM卡加密后的数据
	CurCalc_DataCpy( gCmdBuffer+5, Info, 8 );

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x0d, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );
	return rcode; 
}

/*
**************************************************************************************************************
*
* 函数原型：U32 ICF_ExternalAUTH( U08 PSAMKeyVer, U08 PICCKeyVer, U08 *icc, U08 *citycode )
*
* 函数功能：用户卡外部认证命令
*
* 函数输入：PSAMKeyVer		PSAM密钥版本
*			PICCKeyVer  	用户卡经PSAM卡加密过的数据
*			icc				分散因子
*			citycode		城市代码
*                
* 函数输出：无
*
* 函数返回：0x9000		成功
*			其它值		失败
*   
**************************************************************************************************************
*/
U32 ICF_ExternalAUTH( U08 PSAMKeyVer, U08 PICCKeyVer, U08 *icc, U08 *citycode )
{
	U32 rcode;
	U08 temp[8]={0};

	//取4字节随机数
	rcode = ICF_GetChallenge4B( temp, Gich_Icc );
	if( rcode != 0x9000 )
	{ return rcode; }
    //只有电子现金，行业应用没有发卡
	// if(( memcmp( citycode, "\x00\x00", 2 ) == 0 )||( memcmp( citycode, "\xFF\xFF", 2 ) == 0 ))	
	// { 													       
		
	// 	CurCalc_3DES_Encrypt((U08*)"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", temp, gpRcvBuffer );
	// }										
	// else
	{
		//PSAM卡加密初始化，PCD发给PSAM
		rcode = ICF_InitSamForDes_ToEXAUTN( PSAMKeyVer, icc, citycode, Gich_Sam );
		if( rcode != 0x9000 )
		{ return rcode; }
		//PSAM卡加密，PCD发给PSAM
	 	rcode = ICF_SamDESCrypt_ToEXAUTN( temp, Gich_Sam );
		if( rcode != 0x9000 )
		{ return rcode; }
	}
	//需要保存加密过后的8字节数据
	memcpy( temp, gpRcvBuffer, 8 );

	//对用户卡进行外部认证，PCD发给PICC
	rcode = ICF_ExternalAuthentication( PICCKeyVer, temp, Gich_Icc );
	return rcode;
}

//================================================================================================================
//================================================================================================================
//================================================================================================================
//公交应用相关的特殊指令
//


/*
***************************************************************************************************
*  华虹COS 特殊指令
*  描 述： 读3F00/EC01目录下二进制文件E102,E103,E104  
*
*  参 数： 
*          ich     ich=IC卡接口 ic卡接口定义  下层协议选择
*
*  返 回： ICErrorCode    =0 成功
*                         返回非0时,需要检测ICErrorCodercv_len
*
***************************************************************************************************
*/
U32 ICF_ReadBinaryFile_all( U32 ich )
{
	 U32 rcode;

	gCmdBuffer[0] = 0x00;	//CLA
	gCmdBuffer[1] = 0xB0;	//INS
	gCmdBuffer[2] = 0xFF;	//P1
	gCmdBuffer[3] = 0x00;	//P2
	gCmdBuffer[4] = 0x00;	//Le

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 5, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}


/*
 **************************************************************************************************************
 *         								   获取用户卡安全识别码 
 *
 *  描 述： 获取用户卡安全识别码
 *
 *  返 回： ICErrorCode    =0 成功
 *                         返回非0时,需要检测ICErrorCodercv_len
 *
 **************************************************************************************************************
 */
unsigned short ICF_GetSecuityCode( int ich )
{
	unsigned short rcode;
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0xCA;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0;	//P2
	gCmdBuffer[4] = 9;	//Le

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 5, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}

/*
 **************************************************************************************************************
 *         								   校验用户卡安全识别码 
 *
 *  描 述： 校验用户卡安全识别码
 *
 *  返 回： ICErrorCode    =0 成功
 *                         返回非0时,需要检测ICErrorCodercv_len
 *
 **************************************************************************************************************
 */
unsigned short ICF_CheckSecuityCode( U08 *SecuityCode, int ich )
{
	unsigned short rcode;
	gCmdBuffer[0] = 0x80;	//CLA
	gCmdBuffer[1] = 0xCA;	//INS
	gCmdBuffer[2] = 0x00;	//P1
	gCmdBuffer[3] = 0;	//P2
	gCmdBuffer[4] = 9;	//Le
	memcpy(&gCmdBuffer[5],SecuityCode,9);

	rcode = ICC_APDU_Exchange( ich, gCmdBuffer, 0x0E, gpRcvBuffer, &Grcv_Len, ICC_APDU_Rcv_MAXBUF );
	if( rcode != 0 )
	{ return rcode; }

	if( Grcv_Len < 2 )											//长度判断
	{ return 2;}
	rcode = ( ( gpRcvBuffer[ Grcv_Len - 2 ] << 8 ) | gpRcvBuffer[ Grcv_Len - 1 ] );

	return rcode;
}
